package com.uwlaser.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.uwlaser.http.exception.HttpException;
import com.uwlaser.modules.system.domain.SysExternalHttpLog;
import com.uwlaser.utils.MyHttpUtil;
import com.uwlaser.utils.MyTcpSocketUtil;
import com.uwlaser.utils.enums.DictValueEnum;
import lombok.AllArgsConstructor;
import com.uwlaser.base.PageInfo;
import com.uwlaser.base.QueryHelpMybatisPlus;
import com.uwlaser.base.impl.CommonServiceImpl;
import com.uwlaser.utils.ConvertUtil;
import com.uwlaser.utils.PageUtil;
import com.uwlaser.modules.system.domain.SysExternalSocketLog;
import com.uwlaser.modules.system.service.SysExternalSocketLogService;
import com.uwlaser.modules.system.service.dto.SysExternalSocketLogDto;
import com.uwlaser.modules.system.service.dto.SysExternalSocketLogQueryParam;
import com.uwlaser.modules.system.service.mapper.SysExternalSocketLogMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import java.util.*;

import static cn.hutool.extra.cglib.CglibUtil.toMap;

/**
* @author QZK
* @date 2022-12-06
*/
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = SysExternalSocketLogService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class SysExternalSocketLogServiceImpl extends CommonServiceImpl<SysExternalSocketLogMapper, SysExternalSocketLog> implements SysExternalSocketLogService {

    // private final RedisUtils redisUtils;
    private final SysExternalSocketLogMapper sysExternalSocketLogMapper;

    @Override
    public PageInfo<SysExternalSocketLogDto> queryAll(SysExternalSocketLogQueryParam query, Pageable pageable) {
        IPage<SysExternalSocketLog> queryPage = PageUtil.toMybatisPage(pageable);
        IPage<SysExternalSocketLog> page = sysExternalSocketLogMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
        return ConvertUtil.convertPage(page, SysExternalSocketLogDto.class);
    }

    @Override
    public List<SysExternalSocketLogDto> queryAll(SysExternalSocketLogQueryParam query){
        return ConvertUtil.convertList(sysExternalSocketLogMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), SysExternalSocketLogDto.class);
    }

    @Override
    public SysExternalSocketLog getById(Integer id) {
        return sysExternalSocketLogMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public SysExternalSocketLogDto findById(Integer id) {
        return ConvertUtil.convert(getById(id), SysExternalSocketLogDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(SysExternalSocketLogDto resources) {
        SysExternalSocketLog entity = ConvertUtil.convert(resources, SysExternalSocketLog.class);
        return sysExternalSocketLogMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(SysExternalSocketLogDto resources){
        SysExternalSocketLog entity = ConvertUtil.convert(resources, SysExternalSocketLog.class);
        int ret = sysExternalSocketLogMapper.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeByIds(Set<Integer> ids){
        // delCaches(ids);
        return sysExternalSocketLogMapper.deleteBatchIds(ids);
    }

    /**
     * 添加（不需要事务,保存后异常不回滚）
     * @param log
     * @return
     */
    @Override
    public int addLog(SysExternalSocketLog log) {
        return sysExternalSocketLogMapper.insert(log);
    }

    @Override
    public int reuploadOne(SysExternalSocketLog resources) throws Exception {
        try {
            //请求结果
            String res = "";

            //链接方式，长链接、短链接
            String connectMode = resources.getConnectMode();
            //IP地址
            String host = resources.getHost();
            //端口
            Integer port = resources.getPort();
            //请求参数
            String params = resources.getParams();

            if (MyTcpSocketUtil.LONG_CONNECTION.equals(connectMode)) {
                //长链接请求
                res = MyTcpSocketUtil.sendLongConnectionRequest(host, port, params);
            } else {
                //短链接请求
                res = MyTcpSocketUtil.sendShortConnectionRequest(host, port, params);
            }
            //请求成功,更新状态
            SysExternalSocketLog log = new SysExternalSocketLog();
            log.setId(resources.getId());
            log.setIsSuccess(DictValueEnum.IS_SUCCESS_Y.getValue());//成功
            log.setRequestResult(res);
            log.setRetriesNum(resources.getRetriesNum() + 1);
            sysExternalSocketLogMapper.updateById(log);

        } catch (Exception e) {
            //如果请求失败
            if(e instanceof HttpException){
                SysExternalSocketLog log = new SysExternalSocketLog();
                log.setId(resources.getId());
                log.setRetriesNum(resources.getRetriesNum() + 1);
                log.setErrorMsg(e.getMessage());
                sysExternalSocketLogMapper.updateById(log);
            }
            throw e;
        }
        return 0;
    }

    @Override
    public int reuploadAll() {
        //查询失败的请求
        List<SysExternalSocketLog> logs = sysExternalSocketLogMapper.selectList(new LambdaQueryWrapper<SysExternalSocketLog>()
                .eq(SysExternalSocketLog::getIsSuccess, DictValueEnum.IS_SUCCESS_N.getValue())
                .orderByAsc(SysExternalSocketLog::getId));

        if(logs == null || logs.size() == 0){
            throw new RuntimeException("重传【0】条数据，没有失败的请求可操作重传！");
        }

        //成功数量
        int succeed = 0;
        //失败数量
        int unsuccessful = 0;
        //循环单条上传
        for (SysExternalSocketLog log : logs) {
            try {
                reuploadOne(log);
                succeed ++;
            } catch (Exception e) {
                unsuccessful ++;
            }
        }

        if(unsuccessful != 0){
            throw new RuntimeException("重传【"+logs.size()+"】条数据、成功【"+succeed+"】条、失败【"+unsuccessful+"】条！");
        }

        return succeed;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeById(Integer id){
        Set<Integer> set = new HashSet<>(1);
        set.add(id);
        return this.removeByIds(set);
    }

    /*
    private void delCaches(Integer id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<Integer> ids) {
        for (Integer id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<SysExternalSocketLogDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (SysExternalSocketLogDto sysExternalSocketLog : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("地址", sysExternalSocketLog.getHost());
              map.put("端口", sysExternalSocketLog.getPort());
              map.put("发送参数", sysExternalSocketLog.getParams());
              map.put("连接方式", sysExternalSocketLog.getConnectMode());
              map.put("描述", sysExternalSocketLog.getDescribe());
              map.put("错误消息", sysExternalSocketLog.getErrorMsg());
              map.put("是否成功", sysExternalSocketLog.getIsSuccess());
              map.put("重式次数", sysExternalSocketLog.getRetriesNum());
              map.put("请求返回结果", sysExternalSocketLog.getRequestResult());
              map.put("请求时间", sysExternalSocketLog.getCreateTime());
              map.put("运行耗时", sysExternalSocketLog.getElapsedTime());
                map.put(" createBy",  sysExternalSocketLog.getCreateBy());
                map.put(" updateTime",  sysExternalSocketLog.getUpdateTime());
                map.put(" updateBy",  sysExternalSocketLog.getUpdateBy());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/
}
